我們來看要如何處理爬下的資料吧!
這次我們會應用最近正在風口浪尖的中研院ckip小組開發出的斷詞系統,所以開始時要載入 python 環境才行。
library(tidyverse)
library(tidytext)
library(reticulate)
version <- "3.9.12"
virtualenv_create("my-environment", version = version)
## virtualenv: my-environment
use_virtualenv("my-environment")
os = import("os")
os$listdir(".")
py_available()
## [1] TRUE
確定ok後,接著讀入資料。同時,我們也載入前面提過的停止詞資料。
df_speech_ten <- read_rds("data/國慶演說/df_speech_ten.rds")
df_stopwords <- read_table("data/df_stopword.txt", col_names = F) %>%
rename(id = 1, text_segment = 2) %>% select(text_segment)
df_speech_ten %>% head(5)
## # A tibble: 5 × 3
## year url text
## <chr> <chr> <chr>
## 1 八十六 https://zh.wikisource.org/wiki/總統蒞臨中華民國八十六年國慶大會致詞 " 大會主席、各位貴賓、各位親愛的父老兄弟姐妹:\n 今天是中華民國…
## 2 八十七 https://zh.wikisource.org/wiki/總統蒞臨中華民國八十七年國慶大會致詞 " 大會主席、各位貴賓、各位親愛的父老兄弟姊妹:\n 今天是中華民國…
## 3 八十八 https://zh.wikisource.org/wiki/總統蒞臨中華民國八十八年國慶大會致詞 " 各位女士、各位先生:\n 今天是中華民國八十八年國慶日。每年的這…
## 4 八十九 https://zh.wikisource.org/wiki/總統蒞臨中華民國八十九年國慶大會致詞 " 各位貴賓、各位女士、各位先生:\n 今天是中華民國八十九年國慶,…
## 5 九十 https://zh.wikisource.org/wiki/總統蒞臨中華民國九十年國慶大會致詞 " 各位貴賓、各位女士、各位先生:\n 今天是中華民國九十歲的生日,…
下一步就是斷詞前的資料清理。這次我們做了幾個步驟,先是去除半形與全形空白、分行、tab等。接著則是新增一個重要欄位:西元紀年。因為原文的年份是民國紀年,而且用法又很紛亂,往後在排序和視覺化時將會遇上問題,因此有必要抽取出西元紀年。
具體做法是先提出年份的十位數,接著提出年份的個位數,最後再用數學乘法把兩者整合,加上1911後大功告成。
稍後,我們也補上演講的總統名稱,這樣可以增添後面分析的維度,不僅僅限於年份而已。前面有介紹過要把小寫的台換成大寫的臺,這步驟可以避免日後分析出是。
還有一個關鍵步驟:以句子(sentencese)為單位拆分演說。為什麼要做這一步呢?其實,一般不會想到要做這一步,也不一定要做。因為很多語料本來就有內建章節的概念,無論是學術論文,或者是輕小說,都有明確的結構,但像是新聞還有這次的演說詞沒有,平常這不會是問題,因為我們會有很多很多媒體可以爬,因此資料量很大,但這次我們只有短短二十多年的資料,算是很小的樣本,因此當我們需要一個章節的架構時,就會自己區分,而我的分法就是句子。
df_speech_clean <- df_speech_ten %>%
mutate(text = str_remove_all(text," | |\\n|\\t|\\r")) %>%
mutate(year_ten = str_sub(year, 1, 2)) %>%
mutate(year_zero = str_sub(year, 3, 3)) %>%
mutate(year_ten = case_when(year_ten == "八十" ~ 80,
year_ten == "九十" ~ 90,
year_ten %in% c("一百","一○") ~ 100,
year_ten == "一一" ~ 110,
TRUE ~ as.double(NA))) %>%
mutate(year_zero = case_when(year_zero == "一" ~ 1,
year_zero == "二" ~ 2,
year_zero == "三" ~ 3,
year_zero == "四" ~ 4,
year_zero == "五" ~ 5,
year_zero == "六" ~ 6,
year_zero == "七" ~ 7,
year_zero == "八" ~ 8,
year_zero == "九" ~ 9,
year_zero %in% c("","○") ~ 0,
TRUE ~ as.double(NA))) %>%
mutate(year_full = year_ten + year_zero + 1911) %>%
select(year_full, year, url, text) %>%
mutate(president = case_when(year_full >= 2016 ~ "蔡English",
year_full >= 2008 ~ "馬英九",
year_full >= 2000 ~ "陳水扁",
year_full >= 1997 ~ "李登輝",
TRUE ~ "check")) %>%
mutate(text = str_replace_all(text, "台灣", "臺灣")) %>%
unnest_tokens(sentence, text, token = "sentences") %>%
group_by(president) %>% mutate(sentence_id = row_number()) %>% ungroup() %>%
select(year_full, year, president, sentence_id, sentence)
df_speech_clean %>% head(5)
## # A tibble: 5 × 5
## year_full year president sentence_id sentence
## <dbl> <chr> <chr> <int> <chr>
## 1 1997 八十六 李登輝 1 大會主席、各位貴賓、各位親愛的父老兄弟姐妹:今天是中華民國八十六年國慶日,海內外同胞用熱烈的活動,慶祝我們…
## 2 1997 八十六 李登輝 2 八十六年來,中華民國經歷了許多的挫折和危難,但是,在全體同胞的精誠團結、齊心努力下,終能一再克服挑戰,衝破…
## 3 1997 八十六 李登輝 3 今天,在政治上,我們已經實現了「主權在民」的理想,昂然邁進全民民主的新時代;在經濟上,我們不但締造了舉世矚…
## 4 1997 八十六 李登輝 4 然而,歷史的巨輪不斷向前,國家的發展也永無止境。
## 5 1997 八十六 李登輝 5 面對即將來臨的二十一世紀,我們不能自滿於既有的成就,而必須以更前瞻的思維,和更積極的作為,致力改革,推動建…
# df_speech_clean %>% write_rds("data/df_speech_clean.rds")
下一步就可以準備斷詞了!我們先載入ckip套件,接著讀取模型檔。
### 斷詞預備
ckip <- import("ckiptagger")
# 接著讀取模型檔
ws = ckip$WS("ckip/data") # 斷詞
pos = ckip$POS("ckip/data") # 詞性
ner = ckip$NER("ckip/data") # 實體辨識
### ckip
df_speech_seg <- df_speech_clean %>%
# mutate(text = str_remove_all(text, "\\n|\\r|\\t|:| | ")) %>%
# mutate(text = str_remove_all(text, "[a-zA-Z0-9]+")) %>%
mutate(text_segment= ws(sentence)) %>%
mutate(text_POS = pos(text_segment))
df_speech_seg %>% head(5)
## # A tibble: 5 × 7
## year_full year president sentence_id sentence text_segment text_POS
## <dbl> <chr> <chr> <int> <chr> <list> <list>
## 1 1997 八十六 李登輝 1 大會主席、各位貴賓、各位親愛的父老兄弟姐妹:今天是中華民國八十六年國慶日,海內外同胞… <chr [46]> <chr>
## 2 1997 八十六 李登輝 2 八十六年來,中華民國經歷了許多的挫折和危難,但是,在全體同胞的精誠團結、齊心努力下,… <chr [44]> <chr>
## 3 1997 八十六 李登輝 3 今天,在政治上,我們已經實現了「主權在民」的理想,昂然邁進全民民主的新時代;在經濟上… <chr [101]> <chr>
## 4 1997 八十六 李登輝 4 然而,歷史的巨輪不斷向前,國家的發展也永無止境。 <chr [15]> <chr>
## 5 1997 八十六 李登輝 5 面對即將來臨的二十一世紀,我們不能自滿於既有的成就,而必須以更前瞻的思維,和更積極的… <chr [61]> <chr>
完成斷詞、貼上詞性標籤,接著利用unnest()
將list-column拆開,然後處理詞性的名稱,最後再輸出,就可以等著迎接下一步。
# df_speech_seg %>% write_rds("data/df_speech_seg.rds")
# df_speech_seg <- read_rds("data/df_speech_seg.rds")
### POS結果
df_speech_seg_unnest <- df_speech_seg %>%
mutate(text_segment_l = map_dbl(text_segment, function(x){x %>% length()}),
text_POS_l = map_dbl(text_POS, function(x){x %>% length()})) %>%
filter(text_segment_l == text_POS_l) %>%
filter(text_segment_l != 0) %>%
unnest(c(text_segment, text_POS)) %>%
mutate(text_POS = case_when(
str_detect(text_POS, "CATEGORY") ~ "Puncuation",
str_detect(text_POS, "WHITESPACE") ~ "Whitespace",
str_detect(text_POS, "^D") ~ "Adverb",
str_detect(text_POS, "^N") ~ "Noun",
str_detect(text_POS, "^C") ~ "Conjunction",
str_detect(text_POS, "^V") ~ "Verb",
text_POS == "A" ~ "Adjective",
text_POS == "FW" ~ "FW",
text_POS %in% c("I","P","T") ~ "IPT",
text_POS %in% c("DE","SHI") ~ "DESHI",
TRUE ~ "Others"
)) %>%
filter(!str_detect(text_segment, "[0-9]"))
df_speech_seg_unnest %>% head(5)
## # A tibble: 5 × 9
## year_full year president sentence_id sentence text_segment text_POS text_segment_l text_POS_l
## <dbl> <chr> <chr> <int> <chr> <chr> <chr> <dbl> <dbl>
## 1 1997 八十六 李登輝 1 大會主席、各位貴賓、各位親愛的父老兄弟姐妹:今天是中華民國… 大會 Noun 46 46
## 2 1997 八十六 李登輝 1 大會主席、各位貴賓、各位親愛的父老兄弟姐妹:今天是中華民國… 主席 Noun 46 46
## 3 1997 八十六 李登輝 1 大會主席、各位貴賓、各位親愛的父老兄弟姐妹:今天是中華民國… 、 Puncuat… 46 46
## 4 1997 八十六 李登輝 1 大會主席、各位貴賓、各位親愛的父老兄弟姐妹:今天是中華民國… 各位 Noun 46 46
## 5 1997 八十六 李登輝 1 大會主席、各位貴賓、各位親愛的父老兄弟姐妹:今天是中華民國… 貴賓 Noun 46 46
# df_speech_seg_unnest %>% write_rds("data/df_speech_seg_unnest.rds")